package ru.ssau.customerManagement.controller.remoting;

import com.google.common.collect.Lists;
import ru.ssau.customerManagement.controller.Controller;
import ru.ssau.customerManagement.controller.CreationException;
import ru.ssau.customerManagement.model.entities.Customer;
import ru.ssau.customerManagement.model.entities.CustomerLocation;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.List;

/**
 * Created by illabefat on 22.11.14.
 */
public class ClientController implements Controller {
    private final Socket server;
    private ObjectInputStream in;
    private ObjectOutputStream out;

    public ClientController(Socket server) throws IOException {
        this.server = server;
        in = new ObjectInputStream(this.server.getInputStream());
        out = new ObjectOutputStream(this.server.getOutputStream());
    }

    @Override
    public Customer getCustomer(Long id) {
        OperationResponse response = sendMessage(new OperationRequest("getCustomer", id));
        return (Customer) response.getObject();
    }

    @Override
    public void addCustomer(Customer customer) throws CreationException {
        OperationResponse response = sendMessage(new OperationRequest("addCustomer", customer));
        if (response.getException() != null && response.getException() instanceof CreationException)
            throw (CreationException) response.getException();
    }

    @Override
    public void replaceCustomer(Customer newCustomer) {
        sendMessage(new OperationRequest("replaceCustomer", newCustomer));
    }

    @Override
    public void deleteCustomer(Long customerId) {
        sendMessage(new OperationRequest("deleteCustomer", customerId));
    }

    @Override
    public void addCustomerLocation(CustomerLocation location) throws CreationException {
        OperationResponse response = sendMessage(new OperationRequest("addCustomerLocation", location));
        if (response.getException() != null && response.getException() instanceof CreationException)
            throw (CreationException) response.getException();
    }

    @Override
    public void replaceCustomerLocation(CustomerLocation location) {
        sendMessage(new OperationRequest("replaceCustomerLocation", location));
    }

    @Override
    public CustomerLocation getLocation(Long id) {
        OperationResponse response = sendMessage(new OperationRequest("getLocation", id));
        return (CustomerLocation) response.getObject();
    }

    @Override
    public void deleteCustomerLocation(Long customerLocationId) {
        sendMessage(new OperationRequest("deleteCustomerLocation", customerLocationId));
    }

    @Override
    public List<CustomerLocation> getLocationsByCustomer(Long customerId) {
        OperationResponse response = sendMessage(new OperationRequest("getLocationsByCustomer", customerId));
        return (List<CustomerLocation>) response.getObject();
    }

    @Override
    public List<Customer> getCustomers() {
        OperationResponse response = sendMessage(new OperationRequest("getCustomers"));
        return (List<Customer>) response.getObject();
    }

    @Override
    public boolean tryLockCustomer(Long id) {
        OperationResponse response = sendMessage(new OperationRequest("tryLockCustomer", id));
        return (Boolean) response.getObject();
    }

    @Override
    public void unlockCustomer(Long id) {
        sendMessage(new OperationRequest("unlockCustomer", id));
    }

    @Override
    public boolean tryLockCustomerLocation(Long id) {
        OperationResponse response = sendMessage(new OperationRequest("tryLockCustomerLocation", id));
        return (Boolean) response.getObject();
    }

    @Override
    public void unlockCustomerLocation(Long id) {
        sendMessage(new OperationRequest("unlockCustomerLocation", id));
    }

    private synchronized OperationResponse sendMessage(OperationRequest request) {
        try
        {
            out.writeObject(request);
            out.flush();
            out.reset();

            OperationResponse res = (OperationResponse) in.readObject();
            return res;
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}
